package com.bird.generate.ddd.adapter.database.dataobj

import com.bird.component.database.queryList
import com.bird.component.database.queryOne
import com.bird.component.database.saveValueObjects
import com.bird.component.database.storeEntity
import com.bird.generate.ddd.adapter.database.dataobj.mapper.AggregateRootMapper
import com.bird.generate.ddd.adapter.database.dataobj.mapper.EntityMapper
import com.bird.generate.ddd.adapter.database.dataobj.mapper.FieldMapper
import com.bird.generate.ddd.adapter.database.dataobj.mapper.ValueObjectMapper
import com.bird.generate.ddd.adapter.database.toDO
import com.bird.generate.ddd.adapter.database.toDo
import com.bird.generate.ddd.adapter.database.toEntity
import com.bird.generate.ddd.domain.AggregateRootEntity
import com.bird.generate.ddd.domain.EntityEntity
import com.bird.generate.ddd.domain.ValueObjectEntity
import com.bird.generate.ddd.domain.port.GenerateRepository
import org.springframework.stereotype.Component

/**
 * 生成器仓储适配器
 */
@Component
class GenerateRepositoryAdapter(
    private val aggregateRootMapper: AggregateRootMapper,
    private val fieldMapper: FieldMapper,
    private val entityMapper: EntityMapper,
    private val valueObjectMapper: ValueObjectMapper,
):GenerateRepository {

    /**
     * 查询聚合根实体
     */
    override fun aggregateRootById(id: Long): AggregateRootEntity? {
        //查询聚合根
        return aggregateRootMapper.queryOne {
            eq(AggregateRootDO::id, id)
        }?.toEntity()
            //绑定字段
            .also {root-> root?.fields = fieldMapper.queryList { eq(FieldDO::parentId, root.id).orderByAsc(listOf(FieldDO::sort,FieldDO::id) ) }.map { it.toEntity() } }
            //绑定实体
            .also { root ->
                root?.entities = entityMapper.queryList { eq(EntityDO::aggregateRootId, id) }
                    .map {
                        it.toEntity()
                            //绑定字段
                            .also { entity ->
                                entity.fields =
                                    fieldMapper.queryList {eq(FieldDO::parentId, entity.id).orderByAsc(listOf(FieldDO::sort,FieldDO::id)) }.map { it.toEntity() }
                            }
                    }
            }
            //绑定值对象
            .also { root ->
                root?.valueObjects = valueObjectMapper.queryList { eq(ValueObjectDO::aggregateRootId, id) }
                    .map {
                        it.toEntity()
                            //绑定字段
                            .also { valueObject ->
                                valueObject.fields =
                                    fieldMapper.queryList { eq(FieldDO::parentId, valueObject.id).orderByAsc(listOf(FieldDO::sort,FieldDO::id)) }
                                        .map { it.toEntity() }
                            }
                    }
            }

    }
    /**
     * 保存聚合根实体
     */
    override fun saveAggregateRoot(aggregateRootEntity: AggregateRootEntity) {
        doSaveAggregateRoot(aggregateRootEntity)
        doSaveEntity(aggregateRootEntity,aggregateRootEntity.entities)
        doSaveValueObject(aggregateRootEntity, aggregateRootEntity.valueObjects)
    }

    private fun doSaveValueObject(
        aggregateRootEntity: AggregateRootEntity,
        valueObjects: List<ValueObjectEntity>
    ) {
        valueObjects.forEach {
            valueObjectMapper.storeEntity(it) { it.toDo(aggregateRootEntity.id!!) }
            val fields = it.fields
            //保存字段
            fieldMapper.saveValueObjects(fields.map { field-> field.toDo(it.id!!) }) {
                eq(FieldDO::parentId, it.id!!)
            }
        }
    }

    private fun doSaveEntity(
        aggregateRootEntity: AggregateRootEntity,
        entities: List<EntityEntity>
    ) {
        entities.forEach {
            entityMapper.storeEntity(it) { it.toDO(aggregateRootEntity.id!!) }
            val fields = it.fields
            //保存字段
            fieldMapper.saveValueObjects(fields.map { field-> field.toDo(it.id!!) }) {
                eq(FieldDO::parentId, it.id!!)
            }
        }
    }

    /**
     * 保存聚合根实体
     */
    private fun doSaveAggregateRoot(entity: AggregateRootEntity) {
        aggregateRootMapper.storeEntity(entity) { it.toDO() }
        val fields = entity.fields
        //保存字段
        fieldMapper.saveValueObjects(fields.map { it.toDo(entity.id!!) }) {
            eq(FieldDO::parentId, entity.id!!)
        }
    }
}